/*--------------------------------------------------------------------
 * guc.h
 *
 * External declarations pertaining to backend/utils/misc/guc.c and
 * backend/utils/misc/guc-file.l
 *
 * Portions Copyright (c) 2012-2014, TransLattice, Inc.
 * Copyright (c) 2000-2017, PostgreSQL Global Development Group
 * Written by Peter Eisentraut <peter_e@gmx.net>.
 *
 * This source code file contains modifications made by THL A29 Limited ("Tencent Modifications").
 * All Tencent Modifications are Copyright (C) 2023 THL A29 Limited.
 *
 * src/include/utils/guc.h
 *--------------------------------------------------------------------
 */
#ifndef GUC_H
#define GUC_H

#include "nodes/parsenodes.h"
#include "tcop/dest.h"
#include "utils/array.h"


/* upper limit for GUC variables measured in kilobytes of memory */
/* note that various places assume the byte size fits in a "long" variable */
#if SIZEOF_SIZE_T > 4 && SIZEOF_LONG > 4
#define MAX_KILOBYTES    INT_MAX
#else
#define MAX_KILOBYTES    (INT_MAX / 1024)
#endif

/*
 * Automatic configuration file name for ALTER SYSTEM.
 * This file will be used to store values of configuration parameters
 * set by ALTER SYSTEM command.
 */
#define PG_AUTOCONF_FILENAME        "postgresql.auto.conf"

/*
 * Certain options can only be set at certain times. The rules are
 * like this:
 *
 * INTERNAL options cannot be set by the user at all, but only through
 * internal processes ("server_version" is an example).  These are GUC
 * variables only so they can be shown by SHOW, etc.
 *
 * POSTMASTER options can only be set when the postmaster starts,
 * either from the configuration file or the command line.
 *
 * SIGHUP options can only be set at postmaster startup or by changing
 * the configuration file and sending the HUP signal to the postmaster
 * or a backend process. (Notice that the signal receipt will not be
 * evaluated immediately. The postmaster and the backend check it at a
 * certain point in their main loop. It's safer to wait than to read a
 * file asynchronously.)
 *
 * BACKEND and SU_BACKEND options can only be set at postmaster startup,
 * from the configuration file, or by client request in the connection
 * startup packet (e.g., from libpq's PGOPTIONS variable).  SU_BACKEND
 * options can be set from the startup packet only when the user is a
 * superuser.  Furthermore, an already-started backend will ignore changes
 * to such an option in the configuration file.  The idea is that these
 * options are fixed for a given backend once it's started, but they can
 * vary across backends.
 *
 * SUSET options can be set at postmaster startup, with the SIGHUP
 * mechanism, or from the startup packet or SQL if you're a superuser.
 *
 * USERSET options can be set by anyone any time.
 */
typedef enum
{
    PGC_INTERNAL,
    PGC_POSTMASTER,
    PGC_SIGHUP,
    PGC_SU_BACKEND,
    PGC_BACKEND,
    PGC_SUSET,
    PGC_USERSET
} GucContext;

/*
 * The following type records the source of the current setting.  A
 * new setting can only take effect if the previous setting had the
 * same or lower level.  (E.g, changing the config file doesn't
 * override the postmaster command line.)  Tracking the source allows us
 * to process sources in any convenient order without affecting results.
 * Sources <= PGC_S_OVERRIDE will set the default used by RESET, as well
 * as the current value.  Note that source == PGC_S_OVERRIDE should be
 * used when setting a PGC_INTERNAL option.
 *
 * PGC_S_INTERACTIVE isn't actually a source value, but is the
 * dividing line between "interactive" and "non-interactive" sources for
 * error reporting purposes.
 *
 * PGC_S_TEST is used when testing values to be used later ("doit" will always
 * be false, so this never gets stored as the actual source of any value).
 * For example, ALTER DATABASE/ROLE tests proposed per-database or per-user
 * defaults this way, and CREATE FUNCTION tests proposed function SET clauses
 * this way.  This is an interactive case, but it needs its own source value
 * because some assign hooks need to make different validity checks in this
 * case.  In particular, references to nonexistent database objects generally
 * shouldn't throw hard errors in this case, at most NOTICEs, since the
 * objects might exist by the time the setting is used for real.
 *
 * NB: see GucSource_Names in guc.c if you change this.
 */
typedef enum
{
    PGC_S_DEFAULT,                /* hard-wired default ("boot_val") */
    PGC_S_DYNAMIC_DEFAULT,        /* default computed during initialization */
    PGC_S_ENV_VAR,                /* postmaster environment variable */
    PGC_S_FILE,                    /* postgresql.conf */
    PGC_S_ARGV,                    /* postmaster command line */
    PGC_S_GLOBAL,                /* global in-database setting */
    PGC_S_DATABASE,                /* per-database setting */
    PGC_S_USER,                    /* per-user setting */
    PGC_S_DATABASE_USER,        /* per-user-and-database setting */
    PGC_S_CLIENT,                /* from client connection request */
    PGC_S_OVERRIDE,                /* special case to forcibly set default */
    PGC_S_INTERACTIVE,            /* dividing line for error reporting */
    PGC_S_TEST,                    /* test per-database or per-user setting */
    PGC_S_SESSION                /* SET command */
} GucSource;

/*
 * Parsing the configuration file(s) will return a list of name-value pairs
 * with source location info.  We also abuse this data structure to carry
 * error reports about the config files.  An entry reporting an error will
 * have errmsg != NULL, and might have NULLs for name, value, and/or filename.
 *
 * If "ignore" is true, don't attempt to apply the item (it might be an error
 * report, or an item we determined to be duplicate).  "applied" is set true
 * if we successfully applied, or could have applied, the setting.
 */
typedef struct ConfigVariable
{
    char       *name;
    char       *value;
    char       *errmsg;
    char       *filename;
    int            sourceline;
    bool        ignore;
    bool        applied;
    struct ConfigVariable *next;
} ConfigVariable;

extern bool ParseConfigFile(const char *config_file, bool strict,
                const char *calling_file, int calling_lineno,
                int depth, int elevel,
                ConfigVariable **head_p, ConfigVariable **tail_p);
extern bool ParseConfigFp(FILE *fp, const char *config_file,
              int depth, int elevel,
              ConfigVariable **head_p, ConfigVariable **tail_p);
extern bool ParseConfigDirectory(const char *includedir,
                     const char *calling_file, int calling_lineno,
                     int depth, int elevel,
                     ConfigVariable **head_p,
                     ConfigVariable **tail_p);
extern void FreeConfigVariables(ConfigVariable *list);

/*
 * The possible values of an enum variable are specified by an array of
 * name-value pairs.  The "hidden" flag means the value is accepted but
 * won't be displayed when guc.c is asked for a list of acceptable values.
 */
struct config_enum_entry
{
    const char *name;
    int            val;
    bool        hidden;
};

/*
 * Signatures for per-variable check/assign/show hook functions
 */
typedef bool (*GucBoolCheckHook) (bool *newval, void **extra, GucSource source);
typedef bool (*GucIntCheckHook) (int *newval, void **extra, GucSource source);
typedef bool (*GucUintCheckHook) (uint *newval, void **extra, GucSource source);
typedef bool (*GucRealCheckHook) (double *newval, void **extra, GucSource source);
typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource source);
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);

typedef void (*GucBoolAssignHook) (bool newval, void *extra);
typedef void (*GucIntAssignHook) (int newval, void *extra);
typedef void (*GucUintAssignHook) (uint newval, void *extra);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);

typedef const char *(*GucShowHook) (void);

/*
 * Miscellaneous
 */
typedef enum
{
    /* Types of set_config_option actions */
    GUC_ACTION_SET,                /* regular SET command */
    GUC_ACTION_LOCAL,            /* SET LOCAL command */
    GUC_ACTION_SAVE                /* function SET option, or temp assignment */
} GucAction;

#define GUC_QUALIFIER_SEPARATOR '.'

/*
 * bit values in "flags" of a GUC variable
 */
#define GUC_LIST_INPUT            0x0001    /* input can be list format */
#define GUC_LIST_QUOTE            0x0002    /* double-quote list elements */
#define GUC_NO_SHOW_ALL            0x0004    /* exclude from SHOW ALL */
#define GUC_NO_RESET_ALL        0x0008    /* exclude from RESET ALL */
#define GUC_REPORT                0x0010    /* auto-report changes to client */
#define GUC_NOT_IN_SAMPLE        0x0020    /* not in postgresql.conf.sample */
#define GUC_DISALLOW_IN_FILE    0x0040    /* can't set in postgresql.conf */
#define GUC_CUSTOM_PLACEHOLDER    0x0080    /* placeholder for custom variable */
#define GUC_SUPERUSER_ONLY        0x0100    /* show only to superusers */
#define GUC_IS_NAME                0x0200    /* limit string to NAMEDATALEN-1 */
#define GUC_NOT_WHILE_SEC_REST    0x0400    /* can't set if security restricted */
#define GUC_DISALLOW_IN_AUTO_FILE 0x0800    /* can't set in
                                             * PG_AUTOCONF_FILENAME */

#define GUC_UNIT_KB                0x1000    /* value is in kilobytes */
#define GUC_UNIT_BLOCKS            0x2000    /* value is in blocks */
#define GUC_UNIT_XBLOCKS        0x3000    /* value is in xlog blocks */
#define GUC_UNIT_MB                0x4000    /* value is in megabytes */
#define GUC_UNIT_MEMORY            0xF000    /* mask for size-related units */

#define GUC_UNIT_MS               0x10000    /* value is in milliseconds */
#define GUC_UNIT_S               0x20000    /* value is in seconds */
#define GUC_UNIT_MIN           0x30000    /* value is in minutes */
#define GUC_UNIT_TIME           0xF0000    /* mask for time-related units */

#define GUC_UNIT                (GUC_UNIT_MEMORY | GUC_UNIT_TIME)


/* GUC vars that are actually declared in guc.c, rather than elsewhere */
extern bool log_duration;
extern bool Debug_print_plan;
extern bool Debug_print_parse;
extern bool Debug_print_rewritten;
extern bool Debug_pretty_print;

extern bool log_parser_stats;
extern bool log_planner_stats;
extern bool log_executor_stats;
extern bool log_statement_stats;
extern bool log_btree_build_stats;

#ifdef XCP
extern bool log_gtm_stats;
extern bool log_remotesubplan_stats;
#endif

extern PGDLLIMPORT bool check_function_bodies;
extern bool default_with_oids;

#ifdef _SHARDING_
extern bool default_has_extent;
#endif

#ifdef _PG_ORCL_
extern bool enable_oracle_compatible;
#endif

#ifdef __SUPPORT_DISTRIBUTED_TRANSACTION__
extern bool    support_oracle_compatible;
#endif
#ifdef __OPENTENBASE__
extern int32   g_TransferSpeed;
/* slicent copy from */
extern bool g_enable_copy_silence;
extern bool g_enable_user_authority_force_check;
extern bool enable_buffer_mprotect;
extern bool enable_clog_mprotect;
extern bool enable_tlog_mprotect;
extern bool enable_xlog_mprotect;
extern int query_delay;

extern bool enable_memory_optimization;
extern int max_relcache_relations;
extern int number_replaced_relations;
#endif
extern int    log_min_error_statement;
extern int    log_min_messages;
extern int    client_min_messages;
extern int    log_min_duration_statement;
extern int    log_temp_files;

extern int    temp_file_limit;

extern int    num_temp_buffers;

extern char *cluster_name;
extern char *ConfigFileName;
extern char *HbaFileName;
extern char *IdentFileName;
extern char *external_pid_file;

extern char *application_name;

#ifdef _PG_ORCL_
extern char *nls_date_format;
extern char *nls_timestamp_format;
extern char *nls_timestamp_tz_format;
extern char *nls_sort_locale;
#endif

extern int    tcp_keepalives_idle;
extern int    tcp_keepalives_interval;
extern int    tcp_keepalives_count;
extern int	tcp_user_timeout;

#ifdef _SHARDING_
extern bool g_allow_dml_on_datanode;
extern bool g_allow_force_ddl;
extern bool g_snapshot_for_analyze;
extern bool trace_extent;
#endif

#ifdef __OPENTENBASE__
extern bool g_allow_distri_query_on_standby_node;
#endif

#ifdef XCP
extern char *global_session_string;
#endif
#ifdef TRACE_SORT
extern bool trace_sort;
#endif

#ifdef _SHARDING_
extern int g_ShardVisibleMode;
#endif
/*
 * Functions exported by guc.c
 */
extern void SetConfigOption(const char *name, const char *value,
                GucContext context, GucSource source);

extern void DefineCustomBoolVariable(
                         const char *name,
                         const char *short_desc,
                         const char *long_desc,
                         bool *valueAddr,
                         bool bootValue,
                         GucContext context,
                         int flags,
                         GucBoolCheckHook check_hook,
                         GucBoolAssignHook assign_hook,
                         GucShowHook show_hook);

extern void DefineCustomIntVariable(
                        const char *name,
                        const char *short_desc,
                        const char *long_desc,
                        int *valueAddr,
                        int bootValue,
                        int minValue,
                        int maxValue,
                        GucContext context,
                        int flags,
                        GucIntCheckHook check_hook,
                        GucIntAssignHook assign_hook,
                        GucShowHook show_hook);

extern void DefineCustomUintVariable(
                        const char *name,
                        const char *short_desc,
                        const char *long_desc,
                        uint *valueAddr,
                        uint bootValue,
                        uint minValue,
                        uint maxValue,
                        GucContext context,
                        int flags,
                        GucUintCheckHook check_hook,
                        GucUintAssignHook assign_hook,
                        GucShowHook show_hook);

extern void DefineCustomRealVariable(
                         const char *name,
                         const char *short_desc,
                         const char *long_desc,
                         double *valueAddr,
                         double bootValue,
                         double minValue,
                         double maxValue,
                         GucContext context,
                         int flags,
                         GucRealCheckHook check_hook,
                         GucRealAssignHook assign_hook,
                         GucShowHook show_hook);

extern void DefineCustomStringVariable(
                           const char *name,
                           const char *short_desc,
                           const char *long_desc,
                           char **valueAddr,
                           const char *bootValue,
                           GucContext context,
                           int flags,
                           GucStringCheckHook check_hook,
                           GucStringAssignHook assign_hook,
                           GucShowHook show_hook);

extern void DefineCustomEnumVariable(
                         const char *name,
                         const char *short_desc,
                         const char *long_desc,
                         int *valueAddr,
                         int bootValue,
                         const struct config_enum_entry *options,
                         GucContext context,
                         int flags,
                         GucEnumCheckHook check_hook,
                         GucEnumAssignHook assign_hook,
                         GucShowHook show_hook);

extern void EmitWarningsOnPlaceholders(const char *className);

extern const char *GetConfigOption(const char *name, bool missing_ok,
                bool restrict_superuser);
extern const char *GetConfigOptionResetString(const char *name);
extern void ProcessConfigFile(GucContext context);
extern void InitializeGUCOptions(void);
extern bool SelectConfigFiles(const char *userDoption, const char *progname);
extern void ResetAllOptions(void);
extern void AtStart_GUC(void);
extern int    NewGUCNestLevel(void);
extern void AtEOXact_GUC(bool isCommit, int nestLevel);
extern void BeginReportingGUCOptions(void);
extern void ParseLongOption(const char *string, char **name, char **value);
extern bool parse_int(const char *value, int *result, int flags,
          const char **hintmsg);
extern bool parse_uint(const char *value, uint *result, int flags,
          const char **hintmsg);
extern bool parse_real(const char *value, double *result);
extern int set_config_option(const char *name, const char *value,
                  GucContext context, GucSource source,
                  GucAction action, bool changeVal, int elevel,
                  bool is_reload);
extern void AlterSystemSetConfigFile(AlterSystemStmt *setstmt);
extern char *GetConfigOptionByName(const char *name, const char **varname,
                      bool missing_ok);
extern void GetConfigOptionByNum(int varnum, const char **values, bool *noshow);
extern int    GetNumConfigOptions(void);

extern void SetPGVariable(const char *name, List *args, bool is_local);
extern void GetPGVariable(const char *name, DestReceiver *dest);
extern TupleDesc GetPGVariableResultDesc(const char *name);

#ifdef PGXC
extern char *RewriteBeginQuery(char *query_string, const char *name, List *args);
#endif

extern void ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel);
extern char *ExtractSetVariableArgs(VariableSetStmt *stmt);

extern void ProcessGUCArray(ArrayType *array,
                GucContext context, GucSource source, GucAction action);
extern ArrayType *GUCArrayAdd(ArrayType *array, const char *name, const char *value);
extern ArrayType *GUCArrayDelete(ArrayType *array, const char *name);
extern ArrayType *GUCArrayReset(ArrayType *array);

#ifdef EXEC_BACKEND
extern void write_nondefault_variables(GucContext context);
extern void read_nondefault_variables(void);
#endif

/* GUC serialization */
extern Size EstimateGUCStateSpace(void);
extern void SerializeGUCState(Size maxsize, char *start_address);
extern void RestoreGUCState(void *gucstate);

/* Support for messages reported from GUC check hooks */

extern PGDLLIMPORT char *GUC_check_errmsg_string;
extern PGDLLIMPORT char *GUC_check_errdetail_string;
extern PGDLLIMPORT char *GUC_check_errhint_string;

extern void GUC_check_errcode(int sqlerrcode);

#define GUC_check_errmsg \
    pre_format_elog_string(errno, TEXTDOMAIN), \
    GUC_check_errmsg_string = format_elog_string

#define GUC_check_errdetail \
    pre_format_elog_string(errno, TEXTDOMAIN), \
    GUC_check_errdetail_string = format_elog_string

#define GUC_check_errhint \
    pre_format_elog_string(errno, TEXTDOMAIN), \
    GUC_check_errhint_string = format_elog_string


/*
 * The following functions are not in guc.c, but are declared here to avoid
 * having to include guc.h in some widely used headers that it really doesn't
 * belong in.
 */

/* in commands/tablespace.c */
extern bool check_default_tablespace(char **newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra, GucSource source);
extern void assign_temp_tablespaces(const char *newval, void *extra);

/* in catalog/namespace.c */
extern bool check_search_path(char **newval, void **extra, GucSource source);
extern void assign_search_path(const char *newval, void *extra);

/* in access/transam/xlog.c */
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern void assign_xlog_sync_method(int new_sync_method, void *extra);
extern const char *quote_guc_value(const char *value, int flags);

#endif                            /* GUC_H */
